package com.library.management.service.impl;

import cn.dev33.satoken.session.SaSession;
import cn.dev33.satoken.stp.StpUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.library.management.domain.Sessions;
import com.library.management.domain.Users;
import com.library.management.dto.OnlineUserDTO;
import com.library.management.service.SessionsService;
import com.library.management.mapper.SessionsMapper;
import com.library.management.service.UsersService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;

/**
* @author HY
* @description 针对表【sessions(用户会话表)】的数据库操作Service实现
* @createDate 2025-04-04 17:38:12
*/
@Service
@Slf4j
public class SessionsServiceImpl extends ServiceImpl<SessionsMapper, Sessions>
    implements SessionsService{
    @Autowired
    private UsersService usersService;
    /**
     * 获取在线用户列表
     *
     * @return 在线用户列表
     */
    @Override
    public List<OnlineUserDTO> getOnlineUsers() {
        log.info("获取在线用户列表");

        // 获取所有在线会话
        List<String> sessionIdList = StpUtil.searchSessionId("", 0, -1, false);
        log.info("在线会话数: {}", sessionIdList.size());

        List<OnlineUserDTO> onlineUsers = new ArrayList<>();

        // 遍历会话获取用户信息
        for (String sessionId : sessionIdList) {
            try {
                // 从会话ID中提取用户ID
                SaSession session = StpUtil.getSessionBySessionId(sessionId);
                Object loginIdObj = session.get("loginId");

                if (loginIdObj != null) {
                    Integer userId = Integer.parseInt(loginIdObj.toString());
                    Users user = usersService.getById(userId);

                    if (user != null) {
                        OnlineUserDTO onlineUser = new OnlineUserDTO();
                        onlineUser.setUserId(userId);
                        onlineUser.setUsername(user.getUsername());
                        onlineUser.setRole(user.getRole());

                        // 获取登录IP和时间
                        String loginIp = session.get("loginIp", "");
                        onlineUser.setLoginIp(loginIp);

                        // 登录时间，如果没有则使用会话创建时间
                        Date loginTime = session.get("loginTime", new Date(session.getCreateTime()));
                        onlineUser.setLoginTime(loginTime);

                        // 获取Token值
                        onlineUser.setTokenValue(StpUtil.getTokenValueByLoginId(userId));

                        onlineUsers.add(onlineUser);
                        log.info("获取到在线用户: {}, 角色: {}", user.getUsername(), user.getRole());
                    }
                }
            } catch (Exception e) {
                log.error("处理会话信息时出错: {}", sessionId, e);
            }
        }

        log.info("成功获取在线用户数: {}", onlineUsers.size());
        return onlineUsers;
    }

    /**
     * 强制指定用户退出系统
     *
     * @param userId 用户ID
     * @return 是否成功
     */
    @Override
    public boolean forceLogout(Integer userId) {
        log.info("强制用户退出: userId={}", userId);

        // 检查用户是否存在
        Users user = usersService.getById(userId);
        if (user == null) {
            log.error("用户不存在: userId={}", userId);
            throw new RuntimeException("用户不存在");
        }

        // 获取当前登录用户ID
        try {
            Object loginId = StpUtil.getLoginId();
            Integer currentUserId = Integer.parseInt(loginId.toString());
            // 不允许踢出自己
            if (userId.equals(currentUserId)) {
                log.error("不能踢出当前登录用户");
                throw new RuntimeException("不能踢出当前登录用户");
            }
        } catch (Exception e) {
            log.error("获取当前登录用户ID失败", e);
        }

        try {
            // 踢人下线
            StpUtil.logout(userId);
            log.info("用户 {} 已被强制下线", user.getUsername());
            return true;
        } catch (Exception e) {
            log.error("强制退出用户失败: userId={}, error={}", userId, e.getMessage());
            throw new RuntimeException("强制退出用户失败");
        }
    }
}




